package com.aitoedu.server.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.aitoedu.server.constant.MessageConstant;
import com.aitoedu.server.dto.LoginEmailDTO;
import com.aitoedu.server.dto.RegisterDTO;
import com.aitoedu.server.entity.Student;
import com.aitoedu.server.entity.Teacher;
import com.aitoedu.server.entity.UserRole;
import com.aitoedu.server.exception.AccountNotFoundException;
import com.aitoedu.server.exception.CertErrorException;
import com.aitoedu.server.exception.EmailExistException;
import com.aitoedu.server.exception.PasswordErrorException;
import com.aitoedu.server.mapper.StudentMapper;
import com.aitoedu.server.mapper.TeacherMapper;
import com.aitoedu.server.mapper.UserRoleMapper;
import com.aitoedu.server.vo.LoginVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.aitoedu.server.entity.User;
import com.aitoedu.server.service.UserService;
import com.aitoedu.server.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
* @author 曹正豪
* @description 针对表【user(用户名和密码信息)】的数据库操作Service实现
* @createDate 2024-08-09 00:46:59
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private TeacherMapper teacherMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String from;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    public LoginVO loginEmail(LoginEmailDTO loginEmailDTO) {
        String email = loginEmailDTO.getEmail();
        String password = loginEmailDTO.getPassword();
        User user = userMapper.getByEmail(email);
        if(ObjectUtils.isEmpty(user)){
            throw new AccountNotFoundException(MessageConstant.EMAIL_NOT_FOUND);
        }
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!password.equals(user.getPassword())){
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        LoginVO loginVO = new LoginVO();
        BeanUtils.copyProperties(user,loginVO);
        return loginVO;
    }

    @Override
    public void certify(String email) {
        User user = userMapper.getByEmail(email);
        if(!ObjectUtils.isEmpty(user)){
            throw new EmailExistException(MessageConstant.EMAIL_EXIST);
        }
        Random random = new Random();
        int randomNumber = random.nextInt(90000) + 10000;
        String cert = String.valueOf(randomNumber);
        stringRedisTemplate.opsForValue().set("Cert"+email, cert, 5, TimeUnit.MINUTES);
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(email);
        message.setSubject("AIToEdu");
        message.setText("您的验证码为："+cert+"（五分钟内有效）");
        javaMailSender.send(message);
    }

    @Override
    public void register(RegisterDTO registerDTO) {
        String email = registerDTO.getEmail();
        User user = userMapper.getByEmail(email);
        if(!ObjectUtils.isEmpty(user)){
            throw new EmailExistException(MessageConstant.EMAIL_EXIST);
        }
        String cert = stringRedisTemplate.opsForValue().get("Cert" + email);
        if( (cert==null || cert.isEmpty()) || !registerDTO.getCert().equals(cert)){
            throw new CertErrorException(MessageConstant.CERT_ERROR);
        }
        User temp = new User();
        BeanUtils.copyProperties(registerDTO, temp);
        temp.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()));
        LocalDateTime now = LocalDateTime.now();
        temp.setCreateTime(now);
        temp.setUpdateTime(now);
        userMapper.insert(temp);
        Long id = temp.getId();
        switch (registerDTO.getRole()){
            case 2: setStudent(registerDTO, id, now);break;
            case 1: setTeacher(registerDTO, id, now);break;
        }
        stringRedisTemplate.delete("Cert" + email);
    }

    @Override
    public int getRole() {
        Long userId = Long.valueOf(StpUtil.getLoginId().toString());
        User user = userMapper.selectById(userId);
        return user.getRole();
    }

    private void setStudent(RegisterDTO registerDTO, Long id, LocalDateTime now){
        Student student = new Student();
        BeanUtils.copyProperties(registerDTO, student);
        student.setId(id);
        student.setSname(registerDTO.getUsername());
        student.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()));
        student.setCreateTime(now);
        student.setUpdateTime(now);
        student.setSchool(registerDTO.getSchool());
        studentMapper.insert(student);
        UserRole userRole = UserRole.builder()
                .userId(id)
                .roleId(Long.valueOf(2))
                .build();
        userRoleMapper.insert(userRole);
    }

    private void setTeacher(RegisterDTO registerDTO,  Long id, LocalDateTime now){
        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(registerDTO, teacher);
        teacher.setId(id);
        teacher.setTname(registerDTO.getUsername());
        teacher.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()));
        teacher.setCreateTime(now);
        teacher.setUpdateTime(now);
        teacher.setSchool(registerDTO.getSchool());
        teacherMapper.insert(teacher);
        UserRole userRole = UserRole.builder()
                .userId(id)
                .roleId(Long.valueOf(1))
                .build();
        userRoleMapper.insert(userRole);
    }
}




